package com.easy.core.util;

import java.io.FileInputStream;
import java.lang.reflect.Array;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.ServletContext;

import net.sf.json.JSONArray;
import net.sf.json.JSONException;

import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.easy.base.model.Operator;
import com.easy.base.model.SysConfig;
import com.easy.base.service.SysConfigService;
import com.easy.core.module.OnlineUser;
import com.easy.core.tools.Common;
import com.easy.core.util.PropertiesUtil.Element;
import com.easy.core.util.init.AppStartupAware;

/**
 * <p>Description: App 工具类</p>
 * <p>CreateDate:@2013-8-22</p>
 * @author zhangj
 */
public class AppUtil implements ApplicationContextAware {

	private static Logger					log					=	Logger.getLogger(AppUtil.class);
	private static Map<String, OnlineUser> 	onlineUsers 		= 	new LinkedHashMap<String, OnlineUser>();
	private static Map<String, String> 		configMap 			= 	new HashMap<String, String>();
	private static Map<String, JSONArray>	menuMap				= 	null;
	private static ApplicationContext		applicationContext 	= 	null;
	private static ServletContext			servletContext		= 	null;
	
	public static void init(ServletContext servletContext){
		AppUtil.servletContext = servletContext;
		SysConfigService sysConfigService = getBean("sysConfigService");
		String path = getPathByAppRoot("/WEB-INF/classes/conf/config.properties");
		PropertiesUtil util = new PropertiesUtil();
		FileInputStream in = null;
		try {
			in = new FileInputStream(path);
			util.load(in);
			Iterator<String> it = util.keySet().iterator();
			while(it.hasNext()){
				String key = it.next();
				Element el = util.getElement(key, util.new Element(key, "", ""));
				String value = el.value;
				if(isSynConfig(util)){
					SysConfig config = sysConfigService.findById(key);
					if(null==config){
						sysConfigService.save(new SysConfig(key, value, el.comment));
					}else value = config.getValue();
				}
				configMap.put(key, value);
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		} finally {
			Common.close(log, in);
		}
		try {
			reloadMenu();
		} catch (JSONException e) {
			log.error(e);
		}
		activeStartupEvent();
	}
	
	public static void activeStartupEvent() {
		for(AppStartupAware startup : getBeansByType(AppStartupAware.class)) {
			startup.init();
		}
	}
	
	public static String getAppAbsolutePath() {
		return servletContext.getRealPath("/");
	}
	
	public static String getPathByAppRoot(String path) {
		return servletContext.getRealPath(path);
	}
	
	public static void reloadMenu() throws JSONException{
		
	}
	
	
	public static void addOnlineUser(String sessionid, Operator oper){
		addOnlineUser(sessionid, oper, new HashMap<String, Object>());
	}
	
	public static void addOnlineUser(String sessionid, Operator oper, Map<String, Object> custom){
		if(!onlineUsers.containsKey(sessionid)){
			OnlineUser ou = new OnlineUser();
			ou.setAccount(oper.getAccount());
			ou.setFullname(oper.getFullName());
			ou.setGender(oper.getGender());
			ou.setSessionId(sessionid);
			ou.setUserId(oper.getId());
			ou.setCustom(custom);
			onlineUsers.put(sessionid, ou);
		}
	}
	
	public static void removeOnlineUser(String sessionid){
		onlineUsers.remove(sessionid);
	}
	
	public static Map<String, OnlineUser> getAllOnlineUser(){
		return Collections.unmodifiableMap(onlineUsers);
	}
	
	public static boolean isSynConfig(){
		return !"false".equalsIgnoreCase(configMap.get("app.syn.config"));
	}
	
	protected static boolean isSynConfig(PropertiesUtil proper){
		if(configMap.containsKey("app.syn.config")) return isSynConfig();
		else return "true".equalsIgnoreCase(proper.getProperty("app.syn.config", "false"));
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String beanName) {
		return (T)getApplicationContext().getBean(beanName);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T[] getBeansByType(Class<T> clazz) {
		String[] beanNames = getApplicationContext().getBeanNamesForType(clazz);
		T[] array = (T[]) Array.newInstance(clazz, beanNames.length);
		for(int i = 0; i < beanNames.length; i ++) {
			array[i] = getApplicationContext().getBean(beanNames[i], clazz);
		}
		return array;
	}
	
	public static Map<String, String> getSysConfig() {
		return configMap;
	}
	
	public static Map<String, JSONArray> getMenuMap() {
		return menuMap;
	}
 
	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		if (AppUtil.applicationContext != null) {
			throw new BeanCreationException("ApplicationContextHolder already holded 'applicationContext'.");
		}
		AppUtil.applicationContext = context;
		log.info("holded applicationContext,displayName:" + context.getDisplayName());
	}
	
	public static ApplicationContext getApplicationContext() {
		if (applicationContext == null)
			throw new IllegalStateException("'applicationContext' property is null,ApplicationContextHolder not yet init.");
		return applicationContext;
	}

}
